//
// Created by HP on 2025/11/12.
//
#include <iostream>
#include "../include/emailSender.h"
#include <QtCore/QThread>

EmailSender* EmailSender::instance = nullptr;

bool EmailSender::ensureSocket() {
    // 如果已有 socket 但归属线程不是当前线程，则销毁并在当前线程重建
    if (socket && socket->thread() != QThread::currentThread()) {
        socket.reset();
    }
    if (!socket) {
        socket = std::make_unique<QSslSocket>(); // 在当前线程创建，确保线程亲和性正确
        socket->setPeerVerifyMode(QSslSocket::VerifyPeer);
    }
    if (socket->isOpen()) {
        socket->disconnectFromHost();
        socket->waitForDisconnected(3000);
    }
    return true;
}

int EmailSender::readResponse(QByteArray& response, int timeoutMs) {
    response.clear();
    if (!socket) return -1;

    QElapsedTimer timer;
    timer.start();
    while (timer.elapsed() < timeoutMs) {
        if (!socket->waitForReadyRead(1000)) {
            continue;
        }
        response += socket->readAll();
        const QList<QByteArray> lines = response.split('\n');
        if (lines.isEmpty()) {
            continue;
        }
        // 自后向前查找首个完整响应行
        for (int idx = lines.size() - 1; idx >= 0; --idx) {
            QByteArray line = lines.at(idx);
            if (line.isEmpty()) continue;
            if (line.endsWith('\r')) {
                line.chop(1);
            }
            if (line.size() >= 4 && line.at(3) == ' ') {
                bool ok = false;
                int code = line.left(3).toInt(&ok);
                if (ok) return code;
            }
            // 若是多行响应且末尾带 '-'，继续等完整结束
            if (line.size() >= 4 && line.at(3) == '-') {
                break;
            }
        }
    }
    return -1;
}

bool EmailSender::sendCommand(const QString& command, std::initializer_list<int> expectCodes, int timeoutMs) {
    if (!socket) return false;
    QByteArray response;
    if (socket->write(command.toUtf8()) == -1) {
        std::cerr << "发送命令失败: " << command.toStdString() << std::endl;
        return false;
    }
    if (!socket->waitForBytesWritten(timeoutMs)) {
        std::cerr << "等待写入超时: " << command.toStdString() << std::endl;
        return false;
    }
    int code = readResponse(response, timeoutMs);
    if (code == -1) {
        std::cerr << "SMTP 响应超时或无效，命令: " << command.toStdString() << std::endl;
        return false;
    }
    for (int expect : expectCodes) {
        if (code == expect) {
            return true;
        }
    }
    std::cerr << "SMTP 响应异常，期望 ";
    bool first = true;
    for (int expect : expectCodes) {
        if (!first) std::cerr << "/";
        std::cerr << expect;
        first = false;
    }
    std::cerr << "，收到: " << response.toStdString() << std::endl;
    return false;
}

/**
 * @brief 发送验证码邮件
 * @param to 收件人邮箱地址
 * @param code 验证码
 * @return bool 发送成功返回true，失败返回false
 */
bool EmailSender::sendVerificationCode(const std::string &to, const std::string &code) {
//    std::cout << "发送验证码邮件给 " << to << "，验证码为 " << code << std::endl;
    // 确保套接字初始化
    if (to.empty() || code.empty()) {
        std::cerr << "收件人或验证码为空" << std::endl;
        return false;
    }
    if (!ensureSocket()) {
        std::cerr << "初始化 SMTP 套接字失败" << std::endl;
        return false;
    }

    // 设置SMTP服务器主机和端口
    const QString host = QString::fromStdString(smtp_host);
    bool ok = false;
    const quint16 portValue = QString::fromStdString(smtp_port).toUShort(&ok);
    if (!ok) {
        std::cerr << "SMTP 端口格式错误: " << smtp_port << std::endl;
        return false;
    }

    // 连接到SMTP服务器
    socket->connectToHostEncrypted(host, portValue);
    if (!socket->waitForEncrypted(10000)) {
        std::cerr << "连接 SMTP 服务器失败: " << socket->errorString().toStdString() << std::endl;
        return false;
    }

    // 读取服务器响应
    QByteArray response;
    int codeGreeting = readResponse(response, 10000);
    if (codeGreeting != 220) {
        std::cerr << "SMTP 连接问候失败: " << response.toStdString() << std::endl;
        return false;
    }

    // 执行SMTP命令进行身份验证
    if (!sendCommand("EHLO FlightServer\r\n", 250)) return false;
    if (!sendCommand("AUTH LOGIN\r\n", 334)) return false;

    // 对用户名和密码进行Base64编码
    QByteArray userB64 = QByteArray::fromStdString(smtp_user).toBase64();
    QByteArray passB64 = QByteArray::fromStdString(smtp_password).toBase64();

    // 发送用户名和密码进行认证
    if (!sendCommand(QString::fromLatin1(userB64.append("\r\n")), 334)) return false;
    if (!sendCommand(QString::fromLatin1(passB64.append("\r\n")), 235)) return false;

    // 设置发件人地址
    QString mailFrom = QStringLiteral("MAIL FROM:<%1>\r\n").arg(QString::fromStdString(smtp_from));
    if (!sendCommand(mailFrom, 250)) return false;

    // 设置收件人地址
    QString rcptTo = QStringLiteral("RCPT TO:<%1>\r\n").arg(QString::fromStdString(to));
    if (!sendCommand(rcptTo, {250, 251})) return false;

    // 准备发送邮件数据
    if (!sendCommand("DATA\r\n", 354)) return false;

    // 构建邮件内容
    const QString subject = QStringLiteral("Subject: 铁路航空12316\r\n");
    const QString headers = QStringLiteral("To: %1\r\nFrom: %2\r\nContent-Type: text/plain; charset=utf-8\r\n")
            .arg(QString::fromStdString(to), QString::fromStdString(smtp_from));
    const QString body = QStringLiteral("\r\n欢迎注册12316，您的验证码是：%1，有效期5分钟。\r\n").arg(QString::fromStdString(code));
    const QString message = subject + headers + body + QStringLiteral("\r\n.\r\n");

    // 发送邮件内容
    if (!sendCommand(message, 250, 10000)) return false;

    // 断开与服务器的连接
    sendCommand("QUIT\r\n", 221, 5000);
    std::cout << "验证码邮件已发送至 " << to << std::endl;
    return true;
}